home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Developer Toolbox 6.1
/
SGI Developer Toolbox 6.1 - Disc 4.iso
/
public
/
bit
/
src
/
main.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-01
|
19KB
|
771 lines
/*
* $Id: main.c,v 0.91 1994/02/20 00:52:46 zhao Pre-Release $
*
*. This file is part of BIT shareware package. After the two weeks of
* free evaluation period, you are encouraged (required) to register
* your copy for a small registration fee, which is $35 for personal use
* and $50 for commercial, government and institutional use.
*
* Copyright(c) 1993, 1994 by T.C. Zhao.
* All rights reserved.
*
* Permission to use, copy, and distribute this software in its entirety
* for non-commercial purposes is hereby granted, provided that the
* above shareware and copyright notices and this permission notice
* appear in all copies and their documentation.
*
* This software may be modified for your own use, but modified versions
* may not be distributed without prior consent of the author.
*
* This software is provided "as is" without expressed or implied
* warranty of any kind.
*
*.
*
* Main program for BIT:
* Version identification.
* Parse the command line and walks down or up the file list.
* Wait for Q-events and dispatch handling routines.
*/
#ifndef lint
char *id_main = "$Id: main.c,v 0.91 1994/02/20 00:52:46 zhao Pre-Release $";
#endif
#include "bit.h"
#include <stdlib.h>
#include "global.h"
#include "extern.h"
#include "forms.h"
/*****************************************************************
* current (short) revision identification shown in info panel
******************************************************************/
const char *sver = "BIT ($State: Pre-Release $ $Revision: 0.91 $)";
/******************************************************************
* current (long) version name using -v. Also used by version_cb in
* control.c
******************************************************************/
const char *p_version[] =
{
"bit(Bitmap Image Touchup)"
"$State: Pre-Release $ $Revision: 0.91 $of$Date: 1994/02/20 00:52:46 $",
"Copyright (c) 1993, 1994 by T.C. Zhao", 0
};
static const char *fname; /* current image filename */
/********** local functions (forward) *****/
static void remove_from_list(const char *);
static void special_case(void);
static const char *parse_command_line(int, char *[]);
static int process_Q(void);
/********************************************************************
* Main entry point
********************************************************************/
int
main(int argc, char *argv[])
{
IPTR im;
/* set all options and grab the first filename */
fname = parse_command_line(argc, argv);
/* show help/welcome screen only if there is no arg */
if (argc < 2)
version_cb(0, 0);
/*
* Main loop. Call appropriate functions to handle loading, displaying,
* window manager Q events. Quit when ESC is pressed
*/
do
{
if (fname)
{
/*
* although all text and sgfs are relative to image, there
* might be cases where we want to have them carried over to
* the next image. Must not do this after image is loaded
* because the new image might have its own texts and we
* certainly do not want delete them before displaying.
*/
if (!keepmisc)
{
del_text();
del_marking();
}
#ifdef TIGHT_MEM
/* if last image is large, free memory */
if (imgptr && (imgptr->size > MAXMEMK))
{
free_image_mem(imgptr);
}
#endif
if ((im = load_image(fname)))
{ /* success */
free_image(imgptr);
/*
* This is very important as imgptr is a global
* variable and used in various window manager's event
*/
imgptr = im;
/* display with requested style */
im->io->display(im, display_style, always_clear);
/* if in slidemode, pan */
auto_pan(imgptr);
/*
* check if more than one image present and if yes,
* call the multiple image handler
*/
if (imgptr->more && imgptr->io->inext)
handle_multi_images(imgptr);
}
else
{
/*
* unable to load the darn thing, remove it from the
* active file list
*/
remove_from_list(fname);
/*
* Need special handling if main window is not opened.
* This could happen if fit_image_size is requested
*/
special_case();
}
}
}
while (!process_Q());
clean_up();
return 0;
}
/***************************************************************
* print out all supported formats by calling enumerate_formats,
* which generates a string for each format. print_format will
* just print it out. first is a hack to get 2 formats per line
*****************************************************************/
static int showfmts;
static void
print_format(const char *str)
{
static int first = 1;
fprintf(stderr, (first = !first) ? "%s\n" : " %s\t\t", str);
}
/*************************************************************
* Print current version number and optionally exit
*************************************************************/
static void
print_version(int die)
{
const char **p = p_version;
do
{
fprintf(stderr, "%s\n", rm_rcs_kw(*p));
}
while (*++p);
if (showfmts)
{
fputs("\nBit recognizes the following formats "
"[+:WriteOnly -:ReadOnly]\n", stderr);
enumerate_formats(print_format);
putc('\n', stderr);
}
if (die)
clean_up();
}
/*******************************************************************
* Command line options and messages
*******************************************************************/
static const char *optstr = "hfviIqenabrCRFNc:s:x:y:p:m:d:PS";
static const char *opt = "[-hfvIqenabrCRFN][-x|y f][-m l][-d styl][-s sec]"
"[-c f][-p d]";
/*
* usually only opt is printed, helps will be printed if -h
* is present on command line
*/
static const char *helps[] =
{
"a: enable Automatic initial window placement",
"b: prevent bit from running in Background",
"c: use alternate Configuration file",
"C: show Clock_mailbox window upon startup",
"d: display style [0-16]. Use 100 for cyclic styles",
"e: show Editing panel",
"f: show all supported Formats",
"F: run bit in full screen",
"h: for this Help",
"I: forcing initial window size to be that of the 1st Image",
"m: set to Message output level (0-4), default is 1",
"n: do Not read configuration file",
"N: No initial panels",
"p: default Path",
"q: Quiet mode. Only error message will be printed, same as -m0",
"r: not to Refresh screen before display",
"R: suppress progress report",
"s: pause interval between Slides (in seconds)",
"v: print Version number",
"x: magnification factor in X-direction. 0 for automatic",
"y: magnification factor in Y-direction. 0 for automatic",
0
};
/****************************************************************
* Help messages
****************************************************************/
extern int getopt(int, char *const *, const char *);
static void
usage(const char *cmd, int v)
{
const char **p = helps;
print_version(0);
fprintf(stderr, "Usage: %s %s files\n", cmd, opt);
if (v)
{ /* detailed help */
do
{
fprintf(stderr, "\t%s\n", *p);
}
while (*++p);
}
clean_up();
}
/***********************************************************************
* Do the command line options. Note that we have to preserve all copies
* of the options before init_configure as we want to have the command line
* options to overwrite whatever is set in the configuration file. Nasty!
*************************************************************************/
/* default bit dir. personalized configurations reside there*/
char bitpath[MAXDLEN]; /* bit help/icon files path */
char helppath[MAXDLEN]; /* directory bit launched from */
char startdir[MAXDLEN]; /* start up directory */
char tmppath[MAXDLEN]; /* scratch directory */
static char homedir[MAXDLEN]; /* home directory */
/******************************************************************
* Parse all command line options and overide whatever read
* from the startup file(s). Return the first non-option
* argument
******************************************************************/
int force_pupdraw; /* undocumented */
static const char *
parse_command_line(int argc, char *argv[])
{
int c, noconfig = 0;
const char *firstfile = 0;
extern char *optarg;
char configfile[100];
extern int opterr, optind;
/* copies */
int s_always_clear, s_report;
int s_verbose, s_showedit, s_pause_index;
int s_style;
float s_g_zoomx, s_g_zoomy;
fix_dir_tail(getcwd(startdir, MAXDLEN - 2));
opterr = 0;
strcpy(configfile, "Setup.opt");
while ((c = getopt(argc, argv, optstr)) != EOF)
{
switch (c)
{
case 'S': /* undocumented */
form_single = 1;
break;
case 'P': /* undocumented */
force_pupdraw = 1;
break;
case 'R':
s_report = report_level = 0;
break;
case 'a':
auto_position = 1;
break;
case 'b':
run_in_background = 0;
break;
case 's':
/* allow minimum 0.02 second */
if ((slideshow = (1000.0 * atof(optarg))) < 20)
slideshow = 20;
break;
case 'h':
usage(argv[0], 1);
break;
case 'f':
case 'v':
showfmts = (c == 'f');
print_version(1);
break;
case 'n':
noconfig = 1;
break;
case 'c':
Strncpy(configfile, optarg, sizeof(configfile) - 1);
break;
case 'C':
no_clockmail = 0;
break;
case 'p':
strcpy(bitpath, optarg);
break;
case 'r':
always_clear = 0;
break;
case 'i':
fit_image_size = 1;
break;
case 'I':
fit_image_size = 2;
break;
case 'e':
showedit = !showedit;
break;
case 'm':
verbose = atoi(optarg);
set_msg_threshold(verbose);
break;
case 'd':
display_style = atoi(optarg);
break;
case 'q':
verbose = 0;
break;
case 'x':
/* only supports integer zoom factors */
g_zoomx = atoi(optarg);
break;
case 'y':
/* only supports integer zoom factors */
g_zoomy = atoi(optarg);
break;
case 'F':
full_win = 1;
break;
case 'N':
no_panel = 1;
break;
default:
usage(argv[0], 0);
break;
}
}
if (g_zoomx <= 0.5 || g_zoomy < 0.5)
g_zoomx = g_zoomy = 0.0;
/*
* initialize non-graphics variables, check graphics capabilities,
* initialize forms and open main window. Fonts are initialized in
* display_text.
*/
bit_init();
/*
* note that the load_optfile MUST appear after bit_init because of
* graphics. Also, need to save the variables (can't do the reverse
* either, i.e., store only s_ stuff in parsing, because some of the
* entries in opt panel depends on corresponding variables(bad globals)
*/
s_always_clear = always_clear;
s_verbose = verbose;
s_report = report_level;
s_g_zoomx = g_zoomx;
s_g_zoomy = g_zoomy;
s_showedit = showedit;
s_pause_index = slide_pause_index;
s_style = display_style;
if (!noconfig)
(void) load_optfile(configfile, 1);
/* overwrite the option with command line options */
always_clear = s_always_clear;
slide_pause_index = s_pause_index;
verbose = s_verbose;
g_zoomx = s_g_zoomx;
g_zoomy = s_g_zoomy;
showedit = s_showedit;
report_level = s_report;
display_style = s_style;
/* hints for best image quality */
hardware_constraints(0);
if (optind < argc && (make_list(argc - optind, argv + optind) == 0))
firstfile = next_file();
/*
* if fit_image_size is active and there is no image file specified, need
* to open the main window otherwise there is no way to do that later
*/
if (fit_image_size && firstfile == 0)
{
fit_image_size = 0;
open_main_window(0);
}
return firstfile;
}
/********************************************************************
* Main keyboard handlers: Return -1 for finish keyin, 1 for
* finish all
*******************************************************************/
static int
main_keybd(int key)
{
int ret = 0;
switch (key)
{
case 27: /* ESC */
ret = 1;
break;
}
return ret;
}
/*********************************************************************
* Main loop in main program. After loading and displaying, this routine
* waits for and handles events.
**********************************************************************/
static int
process_Q(void)
{
int done_keyin = 0, ret = 0;
long dev;
static short val;
static const char *func = "Process_Q";
#ifdef MTRACE
M_trace(func, "Enter");
#endif
while (!done_keyin)
{
dev = myqread(&val, LEFTMOUSE, slideshow);
switch ((dev = handle_const_q(dev, val)))
{
case KEYBD:
done_keyin = val && main_keybd(val);
ret = (done_keyin > 0);
break;
case RIGHTMOUSE:
case PKEY:
done_keyin = val && ((fname = prev_file()) != 0);
break;
case SPACEKEY:
case LEFTMOUSE:
done_keyin = (val > 0 && (fname = next_file()) != 0);
break;
case MIDDLEMOUSE:
case CKEY:
done_keyin = val > 0;
break;
default:
if (dev)
M_info(func, "Unknown event dev=%ld val=%d", dev, val);
break;
}
}
#ifdef MTRACE
M_trace(func, "Exit");
#endif
return ret;
}
static void
remove_from_list(const char *s)
{
if (auto_remove == 2 ||
(auto_remove == 1 && yes_no(s, "Remove from list ?", "", 0)))
delete_from_list1(s);
}
/**********************************************************************
* If fit_image is on and first image is bad. If there is still image
* left, open main window and go ahead. Otherwise, quit
**********************************************************************/
static void
special_case(void)
{
if (fit_image_size && win_id < 0)
{
if (is_empty_list())
clean_up();
else
{
fit_image_size = 0;
open_main_window(imgptr);
}
}
}
/*******************************************************************
* For all standard bit files, that is, files from BITDIR, HELPDIR etc
* we buffer all name complete requests.
********************************************************************/
#define NBITFILE 5 /* max. completed filename buffer */
static char bitfile[NBITFILE][MAXDLEN + MAXFLEN];
static int cur_bf;
static FILE *
bitopen(const char *dir, const char *f, const char *m)
{
FILE *fp;
strcat(strcpy(bitfile[cur_bf], dir), f);
if (!(fp = fopen(bitfile[cur_bf], m)))
M_info("BITOPEN", "%s bad open", bitfile[cur_bf]);
cur_bf++;
cur_bf %= NBITFILE;
return fp;
}
#ifndef BITDIR
#define BITDIR "~/.bitrc"
#endif
/******************************************************************
* for any given file, search current dir first, then env variable,
* and default, and $home/.bitrc
*****************************************************************/
#include <sys/stat.h>
FILE *
get_BITfile_fp(const char *name, const char *m)
{
FILE *fp;
const char *p;
if (bitpath[0] == 0)
{ /* first time */
p = getenv("BITDIR");
fix_dir_tail(fix_dirname(strcpy(bitpath, p ? p : BITDIR)));
M_info("", "BITDIR=%s", bitpath);
}
if (access(bitpath, F_OK | X_OK))
{
if (mkdir(bitpath, 0777))
M_warn("BITPATH", "Can't create %s", bitpath);
else
{
errno = 0;
M_info("BITPATH", "Created %s", bitpath);
}
}
if (homedir[0] == 0)
{
if ((p = getenv("HOME")))
strcpy(homedir, p);
fix_dir_tail(fix_dirname(homedir));
M_info("", "HOME=%s", homedir);
strcat(homedir, ".bitrc/");
}
/* try bitpath first */
if ((fp = bitopen(bitpath, name, m)))
{
M_info("getBitFile", "%s found in %s", name, bitpath);
return fp;
}
/* try start up directory */
if ((fp = bitopen(startdir, name, m)))
{
M_info("getBitFile", "%s found in %s", name, startdir);
return fp;
}
/* try current dir */
if ((fp = fopen(name, m)))
return fp;
/* now try home if still not found */
if (!fp && strcmp(homedir, bitpath))
fp = bitopen(homedir, name, m);
/* reset error 'cause previous failure is ok */
if (fp)
errno = 0;
return fp;
}
#ifndef BITHELP
#define BITHELP "/usr/local/lib/bit"
#endif
/********************************************************************
* Given a (help) filename, return the complet path
*********************************************************************/
const char *
get_HELPFile(const char *fn)
{
static char hfile[512];
const char *p;
if (helppath[0] == 0)
{ /* first time */
p = getenv("BITHELP");
fix_dir_tail(fix_dirname(strcpy(helppath, p ? p : BITHELP)));
M_info("", "BITHELP=%s", helppath);
}
return strcat(strcpy(hfile, helppath), fn);
}
FILE *
get_HELPfile_fp(const char *name, const char *m)
{
FILE *fp;
const char *p;
if (helppath[0] == 0)
{ /* first time */
p = getenv("BITHELP");
fix_dir_tail(fix_dirname(strcpy(helppath, p ? p : BITHELP)));
M_info("", "BITHELP=%s", helppath);
}
fp = bitopen(helppath, name, m);
return fp;
}
#ifndef TMPDIR
#define TMPDIR "/usr/tmp"
#endif
const char *
get_TMPfile(const char *name)
{
static char nottmp[MAXDLEN];
char *ret;
if (name[0] == '/' || name[0] == '~')
{
strcpy(nottmp, name);
return fix_dirname(nottmp);
}
if (tmppath[0] == 0)
{
const char *p = getenv("TMPDIR"); /* cpp better be smart */
fix_dir_tail(strcpy(tmppath, p ? p : TMPDIR));
}
ret = strcat(strcpy(bitfile[cur_bf], tmppath), name);
/* advance bitfile buffer */
cur_bf++;
cur_bf %= NBITFILE;
return ret;
}
FILE *
get_TMPfile_fp(const char *name, const char *mode)
{
FILE *fp;
const char *q;
if ((fp = fopen((q = get_TMPfile(name)), mode)))
return fp;
M_err("GetTmpFp", "%s bad open", q);
return 0;
}
/***** remove all RCS keyword from Id ****/
char *
rm_rcs_kw(register const char *s)
{
static char buf[255];
register char *q = buf;
int left = 0, lastc = -1;
while (*s && (q - buf) < sizeof(buf) - 2)
{
switch (*s)
{
case '$':
left = !left;
if (left)
{
while (*s && *s != ':')
s++;
}
break;
default:
/* copy the char and remove extra space */
if (!(lastc == ' ' && *s == ' '))
*q++ = lastc = *s;
break;
}
s++;
}
*q = '\0';
return buf;
}